"""
@author: 江同学呀
@file: geo.py
@date: 2024/7/28 19:25
@desc:
    todo
"""
from typing import Tuple, Dict, Union, List, Literal, Type

from espc.common.common import Number
from espc.err.err import ESPCParamsError
from espc.orm.model.base.base import _Base


class Point(_Base):
    """
    点
    :param lat:
        经度
    :param lon:
        纬度
    :param hash_:
        位置哈希值
    :param string:
        字符串
    :param point:
        点
    """
    def __init__(
            self, lat: Number = None, lon: Number = None, hash_: str = None, string: str = None,
            point: Tuple[Number, Number] = None
    ):
        if not lat and not lon and not hash_ and not string and not point:
            raise ESPCParamsError("参数不能全为空。")
        super().__init__()
        self._lat: Number = lat
        self._lon: Number = lon
        self._string: str = hash_ or string
        self._point: Tuple[Number, Number] = point
        return

    def _build(self) -> Union[str, List[Number], Dict[Literal["lat", "lon"], Number]]:
        if self._point:
            return list(self._point)
        elif self._string:
            return self._string
        return {
            "lat": self._lat,
            "lon": self._lon
        }


class Shape(_Base):
    """
    形状
    """

    def __init__(self, type_: str, coordinates: Tuple[Tuple[Number, Number], Tuple[Number, Number]]):
        super().__init__()
        self._type: str = type_
        self._coordinates: Tuple[Tuple[Number, Number], Tuple[Number, Number]] = coordinates
        return

    def _build(self) -> Dict:
        return {
            "type": self._type,
            "coordinates": self._coordinates
        }


PointType: Type[Union[str, Point, Dict[Literal["lat", "lon"], Number], Tuple[Number, Number]]] = (
    Union[str, Point, Dict[Literal["lat", "lon"], Number], Tuple[Number, Number]]
)


class Bounds(_Base):
    """
    边界
    """

    def __init__(
            self, top_left: PointType = None, bottom_right: PointType = None, top_right: PointType = None,
            bottom_left: PointType = None, topLeft: PointType = None, bottomRight: PointType = None,
            topRight: PointType = None, bottomLeft: PointType = None, top: PointType = None, left: PointType = None,
            bottom: PointType = None, right: PointType = None, *args, **kwargs
    ):
        super().__init__(*args, **kwargs)
        self._top_left: PointType = top_left
        self._bottom_right: PointType = bottom_right
        self._top_right: PointType = top_right
        self._bottom_left: PointType = bottom_left
        self._topLeft: PointType = topLeft
        self._bottomRight: PointType = bottomRight
        self._topRight: PointType = topRight
        self._bottomLeft: PointType = bottomLeft
        self._top: PointType = top
        self._left: PointType = left
        self._bottom: PointType = bottom
        self._right: PointType = right
        return

    def _build(self) -> Dict:
        _body: Dict = {}
        if self._top_left:
            _body["top_left"] = (
                self._top_left._build()
                if isinstance(self._top_left, Point)
                else (
                    list(self._top_left)
                    if isinstance(self._top_left, Tuple)
                    else self._top_left
                )
            )
        if self._bottom_right:
            _body["bottom_right"] = (
                self._bottom_right._build()
                if isinstance(self._bottom_right, Point)
                else (
                    list(self._bottom_right)
                    if isinstance(self._bottom_right, Tuple)
                    else self._bottom_right
                )
            )
        if self._top_right:
            _body["top_right"] = (
                self._top_right._build()
                if isinstance(self._top_right, Point)
                else (
                    list(self._top_right)
                    if isinstance(self._top_right, Tuple)
                    else self._top_right
                )
            )
        if self._bottom_left:
            _body["bottom_left"] = (
                self._bottom_left._build()
                if isinstance(self._bottom_left, Point)
                else (
                    list(self._bottom_left)
                    if isinstance(self._bottom_left, Tuple)
                    else self._bottom_left
                )
            )
        if self._topLeft:
            _body["topLeft"] = (
                self._topLeft._build()
                if isinstance(self._topLeft, Point)
                else (
                    list(self._topLeft)
                    if isinstance(self._topLeft, Tuple)
                    else self._topLeft
                )
            )
        if self._bottomRight:
            _body["bottomRight"] = (
                self._bottomRight._build()
                if isinstance(self._bottomRight, Point)
                else (
                    list(self._bottomRight)
                    if isinstance(self._bottomRight, Tuple)
                    else self._bottomRight
                )
            )
        if self._topRight:
            _body["topRight"] = (
                self._topRight._build()
                if isinstance(self._topRight, Point)
                else (
                    list(self._topRight)
                    if isinstance(self._topRight, Tuple)
                    else self._topRight
                )
            )
        if self._bottomLeft:
            _body["bottomLeft"] = (
                self._bottomLeft._build()
                if isinstance(self._bottomLeft, Point)
                else (
                    list(self._bottomLeft)
                    if isinstance(self._bottomLeft, Tuple)
                    else self._bottomLeft
                )
            )
        if self._top:
            _body["top"] = (
                self._top_left._build()
                if isinstance(self._top_left, Point)
                else (
                    list(self._top_left)
                    if isinstance(self._top_left, Tuple)
                    else self._top_left
                )
            )
        if self._left:
            _body["left"] = (
                self._left._build()
                if isinstance(self._left, Point)
                else (
                    list(self._left)
                    if isinstance(self._left, Tuple)
                    else self._left
                )
            )
        if self._bottom:
            _body["bottom"] = (
                self._bottom._build()
                if isinstance(self._bottom, Point)
                else (
                    list(self._bottom)
                    if isinstance(self._bottom, Tuple)
                    else self._bottom
                )
            )
        if self._right:
            _body["right"] = (
                self._right._build()
                if isinstance(self._right, Point)
                else (
                    list(self._right)
                    if isinstance(self._right, Tuple)
                    else self._right
                )
            )
        return _body

